#include "AbstractTable.h"
#include "CDatabaseManager.h"
#include <QSqlField>

AbstractTable::AbstractTable(const QString &tableName, QObject *parent)
    : QObject{parent},m_strTableName{tableName}
{

}

bool AbstractTable::createTable(const QString &createTabelSql)
{
    return execSql(createTabelSql);
}

/*
    删除表。
    返回值: 成功返回true，失败false
*/
bool AbstractTable::dropTable()
{
    return execSql(QString("drop table %1").arg(m_strTableName));
}

/*
    清空表中所有数据。
    返回值: 成功返回true，失败false
*/
bool AbstractTable::clearTable()
{
    return execSql(QString("delete table %1").arg(m_strTableName));
}

/*
    判断表是否存在。
    返回值: 存在返回true，不存在返回false
*/
bool AbstractTable::exists()
{
    return dbConnection()->tables().contains(m_strTableName);
}

/*
    获取表中数据行数。
    返回值: 数据行数。
*/
int AbstractTable::count()
{
    QSqlQuery query(*dbConnection());
    query.prepare(QString("select count(*) from %1").arg(m_strTableName));
    if(!query.exec()){
        qWarning()<<"query exec error:"<< query.lastError() << query.lastQuery();
        return false;
    }
    if(query.next()){
        return query.value(0).toInt();
    }
    return -1;
}

/*
    获取本线程的数据库连接。
    返回值: 数据库实例。
*/
QSqlDatabase *AbstractTable::dbConnection()
{
    return CDatabaseManager::instance()->getDbConnection();
}

/*
    用于执行无值返回的sql，不适用查询。
    返回值: 执行成功返回true，执行失败false。
*/
bool AbstractTable::execSql(QString strSql)
{
    if(strSql.isEmpty()){
        qWarning()<<"execSql(), sql is empty!";
        return false;
    }
    QSqlQuery query(*dbConnection());
    bool ok = query.exec(strSql);
    if(!ok){
        qWarning()<<"query exec error:"<<query.lastError()<<query.lastQuery();
    }
    return ok;
}

/*
    开启事务。事务具有四个标准属性。
    原子性：保证事务期间所有的操作要么成功要么失败，转账时保证A的扣款和B的转入都成功或都失败。
    一致性：保证正确状态。
    隔离性：事务操作相互独立和透明。
    持久性：已提交的事务在故障时不会丢失。
    参数：无
    返回值: 成功返回true，失败false
*/
bool AbstractTable::transaction()
{
    return dbConnection()->transaction();
}

/*
    提交事务更改。未保存到数据库的事务都会被保存到数据库中。
    参数：无
    返回值: 成功返回true，失败false
*/
bool AbstractTable::commit()
{
    return dbConnection()->commit();
}

/*
    回滚数据，开启事务后如果期间有执行sql失败，可以调用此函数回滚，继续执行其他sql，最后提交。
    参数：无
    返回值: 成功返回true，失败false
*/
bool AbstractTable::rollback()
{
    return dbConnection()->rollback();
}
/*
    添加一行数据，
    参数：
        rowData: 一行数据，<列名,对应值>的形式，常规情况应包含所有列值，除非某些列设置了默认值。
        当主键设置为自增ID时（AUTOINCREMENT），添加一行也不需要指定主键列，会自动生成。
    返回值: 成功返回true，失败false
*/
bool AbstractTable::addRow(const QVariantMap &rowData)
{
    QSqlQuery query(*dbConnection());
    QStringList strList(rowData.count());
    strList.fill("?");
    QString prepareSql = QString("INSERT INTO %1 (%2) VALUES (%3)")
            .arg(m_strTableName,rowData.keys().join(','),strList.join(','));
    query.prepare(prepareSql);
    foreach (QString key, rowData.keys()) {
        query.addBindValue(rowData[key]);
    }

    qDebug() << "prepareSql:" << prepareSql << " bound values:" << query.boundValues();
    if(!query.exec()){
        qWarning()<<"query exec error:"<< query.lastError() << query.lastQuery();
        return false;
    }

    return true;
}
/*
    删除一行数据。
    参数：
        primaryColumnName：主键列名
        var： 对应值
        如： 删除Id为1的一行。deleteRow("Id",1)。

    返回值: 执行成功返回true，删除不存在的值不会导致执行失败。执行失败返回false。
*/
bool AbstractTable::deleteRow(const QString &primaryColumnName, QVariant var)
{
    QSqlQuery query(*dbConnection());
    QString prepareSql = QString("delete from %1 where %2=?").arg(m_strTableName,primaryColumnName);
    query.prepare(prepareSql);
    query.addBindValue(var);
    qDebug() << "prepareSql:" << prepareSql << " bound values:" << query.boundValues();
    if(!query.exec()){
        qWarning()<<"query exec error:"<< query.lastError() << query.lastQuery();
        return false;
    }
    return true;
}

/*
    使用主键约束，更新一行数据
    参数：
        primaryColumnName: 主键列名
        var： 主键约束值
        row： 不包含主键的行数据，<列名，值>
    返回值: 成功返回true，失败false
*/
bool AbstractTable::updateRow(const QString &primaryColumnName, QVariant var, QVariantMap row)
{
    QSqlQuery query(*dbConnection());

    QStringList columnNames;
    foreach (QString columnName, row.keys()) {
        columnNames << columnName + "=?";
    }

    QString prepareSql = QString("update %1 set %2 where %3=?").arg(m_strTableName,columnNames.join(","),primaryColumnName);
    query.prepare(prepareSql);
    foreach (QString columnName, row.keys()) {
        query.addBindValue(row[columnName]);
    }
    query.addBindValue(var);

    qDebug() << "prepareSql:" << prepareSql << " bound values:" << query.boundValues();

    if(!query.exec()){
        qWarning()<<"query exec error:"<< query.lastError() << query.lastQuery();
        return false;
    }
    return true;
}

/*
    查询一行数据。
    参数：
        primaryColumnName: 主键列名
        var： 主键约束值
        如：查询Id为1的行数据，QVariantMap map = queryRow("Id",1);
    返回值: 行数据map，<列名，数据>
*/
QSharedPointer<QVariantMap> AbstractTable::queryRow(QString primaryColumnName, QVariant var)
{
    QSqlQuery query(*dbConnection());
    QString prepareSql = QString("select * from %1 where %2=?").arg(m_strTableName,primaryColumnName);
    query.prepare(prepareSql);
    query.addBindValue(var);
    qDebug() << "prepareSql:" << prepareSql << " bound values:" << query.boundValues();
    QSharedPointer<QVariantMap> varRow(new QVariantMap);
    if(query.exec()){
        QSqlRecord sqlRcd = query.record(); //通过此获取结果列数
        qDebug() << "QSqlRecord:" << sqlRcd;
        while (query.next()) {
            for(int i = 0; i < sqlRcd.count(); i++){
                varRow->insert(sqlRcd.field(i).name(),query.value(i));
            }
        }
    }else{
        qWarning()<<"query exec error:"<< query.lastError() << query.lastQuery();
    }

    return varRow;
}
/*
    查询整表数据。
    参数：无
    返回值: 所有行数据
*/
QSharedPointer<QList<QVariantMap>> AbstractTable::queryAll()
{
    QSqlQuery query(*dbConnection());
    QString prepareSql = QString("select * from %1").arg(m_strTableName);
    query.prepare(prepareSql);
    qDebug() << "prepareSql:" << prepareSql;

    QSharedPointer<QList<QVariantMap>> rowsData(new QList<QVariantMap>);
    if(query.exec()){
        QSqlRecord sqlRcd = query.record(); //通过此获取结果列数
        while (query.next()) {
            QVariantMap varRow;
            for (int i = 0; i < sqlRcd.count(); i++) {
                varRow.insert(sqlRcd.field(i).name(),query.value(i));
            }
            rowsData->append(varRow);
        }
    }else{
        qWarning()<<"query exec error:"<< query.lastError() << query.lastQuery();
    }

    return rowsData;
}

/*
    查询一行中某一列的数据。
    参数：
        primaryColumnName：主键列名
        var: 主键条件值
        columnName: 要查的列名
    返回值: 查询一行数据中的某个列值
*/
QVariant AbstractTable::queryColumn(QString primaryColumnName, QVariant var, QString columnName)
{
    QString prepareSql = QString("select %1 from %2 where %3=?").arg(columnName,m_strTableName,primaryColumnName);

    QSqlQuery query(*dbConnection());
    query.prepare(prepareSql);
    query.addBindValue(var);
    qDebug() << "prepareSql:" << prepareSql << " bound values:" << query.boundValues();
    if (!query.exec() || !query.first()) {
        qWarning()<<"query exec error:"<< query.lastError() << query.lastQuery();
        return QVariant();
    }
    return query.value(0);
}

/*
    更新一行的某个列值。
    参数：
        primaryColumnName：主键列名
        primaryVar: 主键条件值，锁定行
        columnName: 需要更新的列
        newVar： 更新的值
    返回值: 成功返回true，失败返回false
*/
bool AbstractTable::updateColumn(QString primaryColumnName, QVariant primaryVar, QString columnName, QVariant newVar)
{
    QSqlQuery query(*dbConnection());
    QString prepareSql = QString("update %1 set %2 where %3=?").arg(m_strTableName,columnName + "=? ",primaryColumnName);
    query.prepare(prepareSql);
    query.addBindValue(newVar);
    query.addBindValue(primaryVar);
    qDebug() << "prepareSql:" << prepareSql << " bound values:" << query.boundValues();
    if(!query.exec()){
        qWarning()<<"query exec error:"<< query.lastError() << query.lastQuery();
        return false;
    }
    return true;
}
